<template>
  <div class="app-container">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>{{ title }}</span>
        <el-button style="float: right; margin-left: 10px" size="mini" type="success" @click="handleSave">
          <i class="el-icon-check"></i> 保存
        </el-button>
        <el-button style="float: right;" size="mini" @click="handleReturn">
          <i class="el-icon-back"></i> 返回
        </el-button>
      </div>

      <el-tabs v-model="activeTab" type="card">
        <el-tab-pane label="基本信息" name="basic">
          <el-form ref="form" :model="form" :rules="rules" label-width="100px">
            <el-form-item label="报表编码" prop="reportCode">
              <el-input v-model="form.reportCode" placeholder="请输入报表编码" style="width: 400px" maxlength="64" />
            </el-form-item>
            <el-form-item label="报表名称" prop="reportName">
              <el-input v-model="form.reportName" placeholder="请输入报表名称" style="width: 400px" maxlength="100" />
            </el-form-item>
            <el-form-item label="报表类型" prop="reportType">
              <el-select v-model="form.reportType" placeholder="请选择报表类型" style="width: 400px">
                <el-option
                  v-for="dict in dict.type.report_type"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="数据源" prop="dataSource">
              <el-select v-model="form.dataSource" placeholder="请选择数据源" style="width: 400px">
                <el-option
                  v-for="ds in datasourceOptions"
                  :key="ds.dsId"
                  :label="ds.dsName"
                  :value="ds.dsId.toString()"
                ></el-option>
              </el-select>
              <el-button type="primary" size="small" icon="el-icon-plus" @click="openDatasourceDialog" style="margin-left: 10px">新增数据源</el-button>
            </el-form-item>
            <el-form-item label="权限标识" prop="permissionCode">
              <el-input v-model="form.permissionCode" placeholder="请输入权限标识" style="width: 400px" maxlength="100" />
            </el-form-item>
            <el-form-item label="状态" prop="reportStatus">
              <el-radio-group v-model="form.reportStatus">
                <el-radio
                  v-for="dict in dict.type.common_status"
                  :key="dict.value"
                  :label="dict.value"
                >{{ dict.label }}</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item label="备注" prop="remark">
              <el-input
                v-model="form.remark"
                type="textarea"
                placeholder="请输入报表说明"
                maxlength="500"
                style="width: 400px"
              />
            </el-form-item>
          </el-form>
        </el-tab-pane>
        
        <el-tab-pane label="数据设计" name="data">
          <el-form label-width="100px">
            <el-form-item label="SQL语句">
              <div class="sql-editor-container">
                <el-input
                  type="textarea"
                  :autosize="{ minRows: 8, maxRows: 15 }"
                  v-model="dataDesign.sqlQuery"
                  placeholder="请输入SQL查询语句"
                />
              </div>
              <el-button type="primary" size="small" @click="handlePreviewSql" style="margin-top: 10px">执行预览</el-button>
            </el-form-item>
          </el-form>

          <el-table v-if="previewData.columns && previewData.columns.length > 0" :data="previewData.data" border style="width: 100%; margin-top: 15px">
            <el-table-column
              v-for="column in previewData.columns"
              :key="column"
              :prop="column"
              :label="column"
              :show-overflow-tooltip="true"
              align="center"
            />
          </el-table>
          
          <el-empty v-else description="暂无预览数据"></el-empty>
        </el-tab-pane>
        
        <el-tab-pane label="图表设计" name="chart" v-if="form.reportType !== '1'">
          <el-form label-width="100px">
            <el-form-item label="图表类型">
              <el-select v-model="chartDesign.chartType" placeholder="请选择图表类型" style="width: 200px">
                <el-option label="柱状图" value="bar"></el-option>
                <el-option label="折线图" value="line"></el-option>
                <el-option label="饼图" value="pie"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="X轴字段">
              <el-select v-model="chartDesign.xAxisField" placeholder="请选择X轴字段" style="width: 200px">
                <el-option
                  v-for="column in previewData.columns || []"
                  :key="column"
                  :label="column"
                  :value="column"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="Y轴字段">
              <el-select v-model="chartDesign.yAxisField" placeholder="请选择Y轴字段" style="width: 200px">
                <el-option
                  v-for="column in previewData.columns || []"
                  :key="column"
                  :label="column"
                  :value="column"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="图表标题">
              <el-input v-model="chartDesign.title" placeholder="请输入图表标题" style="width: 300px"></el-input>
            </el-form-item>
          </el-form>
          
          <div class="chart-preview">
            <div class="chart-container" ref="chartContainer" style="height: 400px;" v-if="chartDesign.xAxisField && chartDesign.yAxisField"></div>
            <el-empty v-else description="请先选择X轴和Y轴字段"></el-empty>
          </div>
        </el-tab-pane>
        
        <el-tab-pane label="参数设置" name="param">
          <div class="param-toolbar">
            <el-button type="primary" size="small" icon="el-icon-plus" @click="addParameter">新增参数</el-button>
          </div>
          
          <el-table :data="parameters" border style="width: 100%; margin-top: 15px">
            <el-table-column label="参数名称" prop="paramName" min-width="120">
              <template slot-scope="scope">
                <el-input v-model="scope.row.paramName" placeholder="参数名称"></el-input>
              </template>
            </el-table-column>
            <el-table-column label="参数键名" prop="paramKey" min-width="120">
              <template slot-scope="scope">
                <el-input v-model="scope.row.paramKey" placeholder="参数键名"></el-input>
              </template>
            </el-table-column>
            <el-table-column label="参数类型" prop="paramType" width="150">
              <template slot-scope="scope">
                <el-select v-model="scope.row.paramType" placeholder="请选择">
                  <el-option label="字符串" value="string"></el-option>
                  <el-option label="数值" value="number"></el-option>
                  <el-option label="日期" value="date"></el-option>
                  <el-option label="日期时间" value="datetime"></el-option>
                  <el-option label="布尔值" value="boolean"></el-option>
                </el-select>
              </template>
            </el-table-column>
            <el-table-column label="默认值" prop="defaultValue" min-width="120">
              <template slot-scope="scope">
                <el-input v-model="scope.row.defaultValue" placeholder="默认值"></el-input>
              </template>
            </el-table-column>
            <el-table-column label="是否必填" prop="required" width="100">
              <template slot-scope="scope">
                <el-switch v-model="scope.row.required" :active-value="1" :inactive-value="0"></el-switch>
              </template>
            </el-table-column>
            <el-table-column label="排序" prop="paramOrder" width="80">
              <template slot-scope="scope">
                <el-input-number v-model="scope.row.paramOrder" :min="0" :max="99"></el-input-number>
              </template>
            </el-table-column>
            <el-table-column label="操作" align="center" width="100">
              <template slot-scope="scope">
                <el-button
                  size="mini"
                  type="text"
                  icon="el-icon-delete"
                  @click="removeParameter(scope.$index)"
                >删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
        
        <el-tab-pane label="分类设置" name="category">
          <el-transfer
            v-model="selectedCategories"
            :data="allCategories"
            :titles="['可选分类', '已选分类']"
            :props="{
              key: 'categoryId',
              label: 'categoryName'
            }"
          ></el-transfer>
        </el-tab-pane>
      </el-tabs>
    </el-card>
    
    <!-- 数据源对话框 -->
    <el-dialog title="新增数据源" :visible.sync="datasourceDialogVisible" width="600px" append-to-body>
      <el-form ref="datasourceForm" :model="datasourceForm" :rules="datasourceRules" label-width="100px">
        <el-form-item label="数据源名称" prop="dsName">
          <el-input v-model="datasourceForm.dsName" placeholder="请输入数据源名称" />
        </el-form-item>
        <el-form-item label="数据源类型" prop="dsType">
          <el-select v-model="datasourceForm.dsType" placeholder="请选择数据源类型">
            <el-option label="MySQL" value="mysql" />
            <el-option label="Oracle" value="oracle" />
            <el-option label="SQL Server" value="sqlserver" />
            <el-option label="PostgreSQL" value="postgresql" />
          </el-select>
        </el-form-item>
        <el-form-item label="连接URL" prop="jdbcUrl">
          <el-input v-model="datasourceForm.jdbcUrl" placeholder="请输入JDBC连接URL" />
        </el-form-item>
        <el-form-item label="用户名" prop="username">
          <el-input v-model="datasourceForm.username" placeholder="请输入用户名" />
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input v-model="datasourceForm.password" type="password" placeholder="请输入密码" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="testDatasource">测试连接</el-button>
        <el-button type="success" @click="saveDatasource">确 定</el-button>
        <el-button @click="datasourceDialogVisible = false">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { listDatasource, testDatasource, addDatasource } from "@/api/report/datasource";
import { getReport, getReportDesign, saveReportDesign, previewSql, getReportParameters, saveReportParameters, addReport, updateReport } from "@/api/report/report";
import { getCategoryTree, relateCategory } from "@/api/report/category";
import * as echarts from 'echarts';

export default {
  name: "ReportDesign",
  dicts: ['report_type', 'common_status'],
  data() {
    return {
      // 报表ID
      reportId: undefined,
      // 是否为编辑模式
      isEdit: false,
      // 标题
      title: "报表设计",
      // 当前标签页
      activeTab: 'basic',
      // 报表表单
      form: {
        reportId: undefined,
        reportCode: '',
        reportName: '',
        reportType: '0',
        dataSource: '',
        reportStatus: '0',
        permissionCode: '',
        remark: ''
      },
      // 表单校验规则
      rules: {
        reportCode: [
          { required: true, message: "报表编码不能为空", trigger: "blur" },
          { min: 2, max: 64, message: '报表编码长度必须在2到64个字符之间', trigger: 'blur' }
        ],
        reportName: [
          { required: true, message: "报表名称不能为空", trigger: "blur" },
          { min: 2, max: 100, message: '报表名称长度必须在2到100个字符之间', trigger: 'blur' }
        ],
        reportType: [
          { required: true, message: "报表类型不能为空", trigger: "change" }
        ],
        dataSource: [
          { required: true, message: "数据源不能为空", trigger: "change" }
        ]
      },
      // 数据源选项
      datasourceOptions: [],
      // 数据设计
      dataDesign: {
        sqlQuery: ''
      },
      // 图表设计
      chartDesign: {
        chartType: 'bar',
        xAxisField: '',
        yAxisField: '',
        title: ''
      },
      // 预览数据
      previewData: {},
      // 图表实例
      chart: null,
      // 参数列表
      parameters: [],
      // 所有分类
      allCategories: [],
      // 选中的分类
      selectedCategories: [],
      // 设计ID
      designId: undefined,
      // 数据源对话框
      datasourceDialogVisible: false,
      // 数据源表单
      datasourceForm: {
        dsName: '',
        dsType: 'mysql',
        jdbcUrl: '',
        username: '',
        password: ''
      },
      // 数据源表单校验规则
      datasourceRules: {
        dsName: [
          { required: true, message: "数据源名称不能为空", trigger: "blur" },
          { min: 2, max: 100, message: '数据源名称长度必须在2到100个字符之间', trigger: 'blur' }
        ],
        dsType: [
          { required: true, message: "数据源类型不能为空", trigger: "change" }
        ],
        jdbcUrl: [
          { required: true, message: "连接URL不能为空", trigger: "blur" }
        ],
        username: [
          { required: true, message: "用户名不能为空", trigger: "blur" }
        ],
        password: [
          { required: true, message: "密码不能为空", trigger: "blur" }
        ]
      }
    };
  },
  created() {
    this.reportId = this.$route.query.reportId;
    this.isEdit = !!this.reportId;
    
    // 加载数据源选项
    this.loadDatasources();
    
    // 加载分类树
    this.loadCategories();
    
    if (this.isEdit) {
      this.title = "报表设计 - " + this.reportId;
      // 加载报表信息
      this.getReportInfo();
      // 加载设计信息
      this.getDesignInfo();
      // 加载参数信息
      this.getParameters();
    }
  },
  mounted() {
    window.addEventListener('resize', this.resizeChart);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.resizeChart);
    if (this.chart) {
      this.chart.dispose();
      this.chart = null;
    }
  },
  watch: {
    'previewData.data': {
      handler(val) {
        if (val && val.length > 0 && this.chartDesign.xAxisField && this.chartDesign.yAxisField) {
          this.renderChart();
        }
      },
      deep: true
    },
    'chartDesign.chartType': function() {
      if (this.previewData.data && this.previewData.data.length > 0 && this.chartDesign.xAxisField && this.chartDesign.yAxisField) {
        this.renderChart();
      }
    },
    'chartDesign.xAxisField': function() {
      if (this.previewData.data && this.previewData.data.length > 0 && this.chartDesign.xAxisField && this.chartDesign.yAxisField) {
        this.renderChart();
      }
    },
    'chartDesign.yAxisField': function() {
      if (this.previewData.data && this.previewData.data.length > 0 && this.chartDesign.xAxisField && this.chartDesign.yAxisField) {
        this.renderChart();
      }
    },
    'chartDesign.title': function() {
      if (this.chart) {
        const option = this.chart.getOption();
        option.title[0].text = this.chartDesign.title || this.form.reportName;
        this.chart.setOption(option);
      }
    }
  },
  methods: {
    // 加载数据源选项
    loadDatasources() {
      return listDatasource({ pageSize: 100 }).then(response => {
        this.datasourceOptions = response.rows;
      });
    },
    
    // 加载分类树
    loadCategories() {
      getCategoryTree().then(response => {
        this.transformCategoryData(response.data);
      });
    },
    
    // 转换分类数据为transfer组件可用格式
    transformCategoryData(data, parentPath = '') {
      if (!data) return [];
      
      data.forEach(item => {
        const path = parentPath ? `${parentPath} / ${item.categoryName}` : item.categoryName;
        
        // 添加到所有分类列表
        this.allCategories.push({
          categoryId: item.categoryId,
          categoryName: path
        });
        
        // 递归处理子分类
        if (item.children && item.children.length > 0) {
          this.transformCategoryData(item.children, path);
        }
      });
    },
    
    // 获取报表信息
    getReportInfo() {
      getReport(this.reportId).then(response => {
        this.form = response.data;
      });
    },
    
    // 获取设计信息
    getDesignInfo() {
      getReportDesign(this.reportId).then(response => {
        const designData = response.data;
        if (designData) {
          this.designId = designData.designId;
          
          // 解析设计内容
          try {
            const designContent = JSON.parse(designData.designContent || '{}');
            this.dataDesign.sqlQuery = designContent.sqlQuery || '';
            this.chartDesign.chartType = designContent.chartType || 'bar';
            this.chartDesign.xAxisField = designContent.xAxisField || '';
            this.chartDesign.yAxisField = designContent.yAxisField || '';
            this.chartDesign.title = designContent.title || '';
            
            // 预览SQL
            if (this.dataDesign.sqlQuery) {
              this.handlePreviewSql();
            }
          } catch (error) {
            console.error("解析设计内容失败", error);
          }
        }
      });
    },
    
    // 获取参数信息
    getParameters() {
      getReportParameters(this.reportId).then(response => {
        this.parameters = response.data || [];
      });
    },
    
    // 执行SQL预览
    handlePreviewSql() {
      if (!this.dataDesign.sqlQuery) {
        this.$message.warning("请输入SQL查询语句");
        return;
      }
      
      const previewData = {
        reportId: this.reportId,
        dataSource: this.form.dataSource,
        sqlQuery: this.dataDesign.sqlQuery
      };
      
      previewSql(previewData).then(response => {
        this.previewData = response.data;
        
        // 自动选择前两列作为X轴和Y轴
        if (this.previewData.columns && this.previewData.columns.length >= 2 && !this.chartDesign.xAxisField) {
          this.chartDesign.xAxisField = this.previewData.columns[0];
          this.chartDesign.yAxisField = this.previewData.columns[1];
        }
      });
    },
    
    // 渲染图表
    renderChart() {
      if (!this.chartDesign.xAxisField || !this.chartDesign.yAxisField) return;
      
      const xAxisField = this.chartDesign.xAxisField;
      const yAxisField = this.chartDesign.yAxisField;
      const chartType = this.chartDesign.chartType;
      const title = this.chartDesign.title || this.form.reportName;
      
      this.$nextTick(() => {
        if (this.chart) {
          this.chart.dispose();
        }
        
        if (!this.$refs.chartContainer) return;
        
        this.chart = echarts.init(this.$refs.chartContainer);
        
        const xAxisData = [];
        const seriesData = [];
        
        this.previewData.data.forEach(item => {
          xAxisData.push(item[xAxisField]);
          seriesData.push(item[yAxisField]);
        });
        
        let option;
        
        if (chartType === 'bar' || chartType === 'line') {
          option = {
            title: {
              text: title,
              left: 'center'
            },
            tooltip: {
              trigger: 'axis'
            },
            xAxis: {
              type: 'category',
              data: xAxisData
            },
            yAxis: {
              type: 'value'
            },
            series: [{
              name: yAxisField,
              type: chartType,
              data: seriesData
            }]
          };
        } else if (chartType === 'pie') {
          const pieData = this.previewData.data.map(item => {
            return {
              name: item[xAxisField],
              value: item[yAxisField]
            };
          });
          
          option = {
            title: {
              text: title,
              left: 'center'
            },
            tooltip: {
              trigger: 'item',
              formatter: '{a} <br/>{b} : {c} ({d}%)'
            },
            legend: {
              orient: 'vertical',
              left: 'left',
              data: xAxisData
            },
            series: [{
              name: yAxisField,
              type: 'pie',
              radius: '55%',
              center: ['50%', '60%'],
              data: pieData
            }]
          };
        }
        
        this.chart.setOption(option);
      });
    },
    
    // 调整图表大小
    resizeChart() {
      if (this.chart) {
        this.chart.resize();
      }
    },
    
    // 添加参数
    addParameter() {
      this.parameters.push({
        paramName: '',
        paramKey: '',
        paramType: 'string',
        defaultValue: '',
        required: 0,
        paramOrder: this.parameters.length
      });
    },
    
    // 删除参数
    removeParameter(index) {
      this.parameters.splice(index, 1);
      // 重新调整序号
      this.parameters.forEach((item, idx) => {
        item.paramOrder = idx;
      });
    },
    
    // 保存报表
    handleSave() {
      this.$refs.form.validate(valid => {
        if (!valid) {
          this.$message.error("请完善基本信息");
          this.activeTab = 'basic';
          return;
        }
        
        if (!this.dataDesign.sqlQuery) {
          this.$message.error("请输入SQL查询语句");
          this.activeTab = 'data';
          return;
        }
        
        // 检查参数
        let paramValid = true;
        this.parameters.forEach((param, index) => {
          if (!param.paramName || !param.paramKey) {
            this.$message.error(`第 ${index + 1} 个参数的名称和键名不能为空`);
            this.activeTab = 'param';
            paramValid = false;
          }
        });
        
        if (!paramValid) return;
        
        // 保存报表定义
        const saveData = Object.assign({}, this.form);
        
        const saveFunc = this.isEdit ? updateReport : addReport;
        
        saveFunc(saveData).then(response => {
          // 获取或设置报表ID
          const reportId = this.isEdit ? this.reportId : response.data;
          
          // 保存设计内容
          const designContent = JSON.stringify({
            sqlQuery: this.dataDesign.sqlQuery,
            chartType: this.chartDesign.chartType,
            xAxisField: this.chartDesign.xAxisField,
            yAxisField: this.chartDesign.yAxisField,
            title: this.chartDesign.title
          });
          
          const designData = {
            reportId: reportId,
            designId: this.designId,
            designContent: designContent
          };
          
          return saveReportDesign(designData).then(() => reportId);
        }).then(reportId => {
          // 保存参数
          const paramData = this.parameters.map(param => {
            return {
              ...param,
              reportId: reportId
            };
          });
          
          return saveReportParameters({ reportId, params: paramData }).then(() => reportId);
        }).then(reportId => {
          // 保存分类关联
          if (this.selectedCategories.length > 0) {
            return relateCategory({
              reportId: reportId,
              categoryIds: this.selectedCategories
            }).then(() => reportId);
          }
          return reportId;
        }).then(() => {
          this.$modal.msgSuccess("保存成功");
          this.handleReturn();
        }).catch(() => {
          this.$modal.msgError("保存失败");
        });
      });
    },
    
    // 返回列表
    handleReturn() {
      this.$router.push({ path: '/report/list' });
    },
    
    // 打开新增数据源对话框
    openDatasourceDialog() {
      this.datasourceForm = {
        dsName: '',
        dsType: 'mysql',
        jdbcUrl: '',
        username: '',
        password: ''
      };
      this.datasourceDialogVisible = true;
    },
    
    // 测试数据源连接
    testDatasource() {
      this.$refs.datasourceForm.validate(valid => {
        if (valid) {
          const loading = this.$loading({
            lock: true,
            text: '正在测试连接...',
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          });
          
          testDatasource(this.datasourceForm).then(response => {
            loading.close();
            this.$modal.msgSuccess('连接成功');
          }).catch(() => {
            loading.close();
          });
        }
      });
    },
    
    // 保存数据源
    saveDatasource() {
      this.$refs.datasourceForm.validate(valid => {
        if (valid) {
          const loading = this.$loading({
            lock: true,
            text: '正在保存数据源...',
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          });
          
          addDatasource(this.datasourceForm).then(response => {
            loading.close();
            this.$modal.msgSuccess('新增数据源成功');
            this.datasourceDialogVisible = false;
            
            // 重新加载数据源列表
            this.loadDatasources().then(() => {
              // 自动选择新创建的数据源
              if (response.data) {
                this.form.dataSource = response.data.toString();
              }
            });
          }).catch(() => {
            loading.close();
          });
        }
      });
    }
  }
};
</script>

<style scoped>
.sql-editor-container {
  width: 100%;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.chart-preview {
  margin-top: 20px;
  border: 1px solid #ebeef5;
  padding: 20px;
  border-radius: 4px;
}

.param-toolbar {
  margin-bottom: 10px;
}

.el-transfer {
  margin: 20px 0;
  text-align: center;
}
</style> 